const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`; // aa-aa 
const qnameCapture = `((?:${ncname}\\:)?${ncname})`; //aa:aa
// 匹配开始标签
const startTagOpen = new RegExp(`^<${qnameCapture}`); // 可以匹配到标签名  [1]
// 匹配结束标签
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`); //[0] 标签的结束名字
//    style="xxx"   style='xxx'  style=xxx
// 匹配属性
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/;
// 匹配自闭和标签
const startTagClose = /^\s*(\/?)>/;







// <div id="app" style="color: orange; font-size: 100px">
// prev
// <h1>{{a}} aa {{b}}</h1>
// next
// </div>

// 解析字符串
export function parse(template) {
    // 元素
    function createAstElement(tagName, attrs) {
        return {
            tag: 1,
            tagName,
            attrs,
            children: [],
            // 父亲用栈来存储
            parent: null
        }
    }
    let root;// 根树
    let stack = [];
    // let currentParentStack = []; // 解析开始标签的时候，供文本元素确定父亲
    let currentParent;

    function start(tagName, attrs) {
        // 创建ast
        let element = createAstElement(tagName, attrs);
        if (!root) {
            root = element;
        }
        // currentParentStack.push(element);
        currentParent = element;
        stack.push(element);
    }

    function text(text) {
        if (text) {
            currentParent.children.push({
                type: 3,
                text,
                parent: currentParent
            })
        }
        // currentParentStack[currentParentStack.length - 1].children.push({
        //     type: 3,
        //     text
        // })
    }

    function end() {
        let child = stack.pop();
        // 弹出后取出最后一个，保证元素的后面还是文本或元素的等找到的父亲
        currentParent = stack[stack.length - 1];
        if (currentParent) {
            currentParent.children.push(child);
            child.parent = currentParent;
        }
        // currentParentStack.pop();
    }
    // 不停的截取
    while (template) {
        let index = template.indexOf('<');
        // 可能是开始标签，也可能是结束标签
        if (index === 0) {
            // 解析开始标签和标签内属性

            // 解析结束标签
            let match = template.match(endTag);
            if (match) { // 匹配到结束标签
                let endTag = match[1];// 得到结束标签名
                end(endTag);
                subTemplate(match[0].length);
                continue;
            } else {
                let { tagName, attrs } = parseStart(template);
                start(tagName, attrs);
                continue;
            }
        }
        let txt;
        if (index > 0) {
            // 处理文本
            txt = template.slice(0, index);
            text(txt.replace(/\s/g, ''));
            subTemplate(txt.length);
            // 接下来又要处理开始标签
            continue;
        }
    }
    function parseStart() {
        let obj = {
            attrs: []
        };
        // 1)得到标签名
        let match = template.match(startTagOpen);
        obj.tagName = match[1];
        // 截取字符串，继续解析
        subTemplate(match[0].length);

        // 2)解析属性
        // 1 不是闭合标签 2 能匹配到属性
        let end,
            attr;
        while (!(end = template.match(startTagClose)) && (attr = template.match(attribute))) {
            obj.attrs.push({
                name: attr[1],
                value: attr[3] || attr[4] || attr[5] // id="app" id='app' id=app
            })
            // 截掉获取的字符串
            subTemplate(attr[0].length);
        }
        // 到这说明已经没有属性了或者到结束标签了，一般这两个条件都是一起满足
        if (end) {
            subTemplate(end[0].length);
            return obj;
        }
    }

    function subTemplate(length) {
        template = template.substring(length);
    }
    return root;
}